package com.syl.orm.spring;

import com.syl.orm.ibatis.SqlSession;
import com.syl.orm.ibatis.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.FactoryBean;

import javax.annotation.Resource;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Collection;
import java.util.List;

/**
 * @Description: 代理生成Mapper
 * @author: YunLong
 * @date: 2022-08-29 15:43
 **/
public class EsMapperFactoryBean<T> implements FactoryBean<T> {
    private Logger logger = LoggerFactory.getLogger(EsMapperFactoryBean.class);

    private Class<T> mapperInterface;
    @Resource
    private SqlSessionFactory esSqlSessionFactory;

    public EsMapperFactoryBean(Class<T> mapperInterface) {
        this.mapperInterface = mapperInterface;
    }


    @Override
    public T getObject() throws Exception {
        InvocationHandler handler = (proxy, method, args) -> {
            logger.info("你被代理了，执行ES-SQL操作！{}", method.getName());
            // 如果是Object中定义的方法，直接执行。如toString(),hashCode()等
            if (Object.class.equals(method.getDeclaringClass())) {
                return method.invoke(this, args);
            }
            try {
                SqlSession sqlSession = esSqlSessionFactory.openSession();
                try {
                    Class<?> returnType = method.getReturnType();
                    boolean asList = Collection.class.isAssignableFrom(returnType);
                    if (asList) {
                        return sqlSession.selectList(mapperInterface.getName() + "." + method.getName(), args);
                    }
                    return sqlSession.selectOne(mapperInterface.getName() + "." + method.getName(), args[0]);
                } finally {
                    sqlSession.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            return method.getReturnType().newInstance();
        };
        return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{mapperInterface}, handler);
    }

    @Override
    public Class<?> getObjectType() {
        return mapperInterface;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

}
